package vista.ventanas;

import vista.objetos.FabricaEntidadGraficable;
import vista.paneles.ElementoNoExistenteException;
import vista.paneles.NingunElementoSeleccionadoException;
import vista.paneles.NoEsNodoPadre;
import vista.paneles.PanelIdentificadores;
import vista.paneles.PanelParLabelCombo;
import vista.paneles.PanelParLabelText;
import vista.paneles.PanelReferenciaEntidades;

import java.awt.Insets;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.MouseListener;
import java.util.List;

import javax.swing.JFrame;

import logica.AtributoIdentificadorFaltanteException;
import logica.AtributoRepetidoException;
import logica.Entidad;
import logica.EntidadIdentificadoraFaltanteException;
import logica.IdExternoRepetidoException;
import logica.Identificador;
import logica.IdentificadorVacioException;
import logica.SinNombreException;

@SuppressWarnings("serial")
public class VentanaEntidad extends SubVentanaConPanelAtributos implements IVentanaConReferenciaAEntidades {

	private PanelParLabelText panelNombre;
	private PanelParLabelCombo panelTipo;
	private PanelReferenciaEntidades panelReferenciaEntidadesExternas;
	private PanelIdentificadores panelIdentificadores;
	
	/*estos atributos son para la edicion*/
	private Entidad entidad;

	public VentanaEntidad(JFrame ventana, List<FabricaEntidadGraficable> tipos)
	{
		super(ventana, "Entidad Nueva", ConstantesVista.ALTO_DIALOGOS );
		
		agregarTipos(tipos);
		
		this.entidad = null;
	}
	
	public VentanaEntidad(JFrame ventanaPadre, List<FabricaEntidadGraficable> tipos, Entidad entidadAEditar) throws ElementoNoExistenteException
	{
		super(ventanaPadre, "Entidad A Editar", ConstantesVista.ALTO_DIALOGOS );
		
		agregarTipos(tipos);
		
		this.entidad = entidadAEditar;
		this.setInformacionEntidadAEditar();
	}

	private void setInformacionEntidadAEditar() throws ElementoNoExistenteException 
	{
		this.panelNombre.setInformacion(entidad.getNombre());
		this.panelTipo.seleccionarDato(entidad.getTipo());
		this.getPanelAtributo().agregarAtributos(entidad.getAtributos());
		this.panelReferenciaEntidadesExternas.agregarEntidadesExternas(entidad.getReferenciaAEntidadesExternas());
		this.panelIdentificadores.agregarIdentificadores(entidad.getIdentificadores());
	}
	
	public Entidad getEntidad() throws AtributoRepetidoException, IdExternoRepetidoException, SinNombreException, AtributoIdentificadorFaltanteException, EntidadIdentificadoraFaltanteException, IdentificadorVacioException, NingunElementoSeleccionadoException
	{

		if (entidad == null )
			entidad = new Entidad(this.getNombreEntidad());
		else
			entidad.setNombre(this.getNombreEntidad());
		
		entidad.setTipo(this.getTipoDeEntidad().getTipoDeEntidad());
		entidad.setAtributos(this.getAtributos());
		entidad.setReferenciasExternas(this.getReferenciasExternas());
		entidad.setIdentificadores(this.getIdentificadores());
		
		return entidad;	
	}

	public String getNombreEntidad() {
		return this.panelNombre.getInformacion();
	}
	
	private List<Identificador> getIdentificadores() {
		return this.panelIdentificadores.getIdentificadores();
	}
	
	public List<Entidad> getReferenciasExternas() {
		return this.panelReferenciaEntidadesExternas.getReferenciaEntidades();
	}

	public FabricaEntidadGraficable getTipoDeEntidad() throws NingunElementoSeleccionadoException
	{
		try
		{
			return (FabricaEntidadGraficable) this.panelTipo.getDatoSeleccionado();
		}
		catch(NingunElementoSeleccionadoException nada)
		{// se supone q no debe pasar porq siempre tiene seleccion por default
			throw new NingunElementoSeleccionadoException("No se seleccionó ningún tipo de Entidad");
		}
		
	}

	/*para los eventos*/
	@Override
	public void escucharEventoAgregarEntidad(MouseListener controlador) {
		this.panelReferenciaEntidadesExternas.escucharEventoAgregar(controlador);
	}
	
	@Override
	public void escucharEventoQuitarEntidad(MouseListener controlador) {
		this.panelReferenciaEntidadesExternas.escucharEventoQuitar(controlador);
	}
	
	@Override
	public void agregarEntidadExterna(Entidad entidad) {
		this.panelReferenciaEntidadesExternas.agregarEntidadExterna(entidad);	
	}
	
	@Override
	public void quitarEntidadExterna() {
		this.panelReferenciaEntidadesExternas.quitarEntidadExterna();
	}
	
	public void escucharEventoAgregarIdentificador(MouseListener controlador) {
		this.panelIdentificadores.escucharEventosBotonNuevo(controlador);	
	}
	
	public void escucharEventoQuitarIdentificador(MouseListener controlador) {
		this.panelIdentificadores.escucharEventosBotonEliminar(controlador);
	}
	
	public void agregarIdentificador(Identificador identificador) {
		this.panelIdentificadores.agregarIdentificador(identificador);	
	}
	
	public void quitarIdentificador() throws NoEsNodoPadre {
		this.panelIdentificadores.quitarIdentificador();
	}

	/*para dibujar la ventana*/
	
	private void agregarTipos(List<FabricaEntidadGraficable> tipos) {
		this.panelTipo.setDatosCombo(tipos);		
	}
	
	@Override
	protected void agregarComponentesPanelInformacion() 
	{
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{0, 0};
		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0};
		gridBagLayout.columnWeights = new double[]{1.0};
		gridBagLayout.rowWeights = new double[]{1.0, 1.0, 1.0, 1.0, 1.0};
		
		getPanelDeInformacion().setLayout(gridBagLayout);
		
		agregarPanelNombre();
		agregarPanelTipo();
		agregarPanelAtributos();	
		agregarPanelReferenciaEntidadesExternas();
		agregarPanelIdentificadores();
	}
	
	private void agregarPanelNombre()
	{
		this.panelNombre = new PanelParLabelText("Nombre");
		
		GridBagConstraints gbc_panelNombre = new GridBagConstraints();
		gbc_panelNombre.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelNombre.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelNombre.gridx = 0;
		gbc_panelNombre.gridy = 0;
		
		this.getPanelDeInformacion().add(this.panelNombre, gbc_panelNombre);
	}

	private void agregarPanelTipo() 
	{
		this.panelTipo = new PanelParLabelCombo("Tipo");
		
		GridBagConstraints gbc_panelTipo = new GridBagConstraints();
		gbc_panelTipo.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelTipo.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelTipo.gridx = 0;
		gbc_panelTipo.gridy = 1;
		
		this.getPanelDeInformacion().add(this.panelTipo, gbc_panelTipo);
	}

	private void agregarPanelAtributos() 
	{
		GridBagConstraints gbc_panelAtributos = new GridBagConstraints();
		gbc_panelAtributos.fill = GridBagConstraints.BOTH;
		gbc_panelAtributos.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelAtributos.gridx = 0;
		gbc_panelAtributos.gridy = 2;
		
		this.getPanelDeInformacion().add(getPanelAtributo(), gbc_panelAtributos);
	}	
	
	private void agregarPanelReferenciaEntidadesExternas() 
	{
		this.panelReferenciaEntidadesExternas = new PanelReferenciaEntidades("Entidades Identificadoras");
		
		GridBagConstraints gbc_panelRefExterna = new GridBagConstraints();
		gbc_panelRefExterna.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelRefExterna.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelRefExterna.gridx = 0;
		gbc_panelRefExterna.gridy = 3;
		
		this.getPanelDeInformacion().add(this.panelReferenciaEntidadesExternas, gbc_panelRefExterna);
	}
	
	private void agregarPanelIdentificadores()
	{
		this.panelIdentificadores = new PanelIdentificadores("Identificadores");
		
		GridBagConstraints gbc_panelIdentificadores = new GridBagConstraints();
		gbc_panelIdentificadores.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelIdentificadores.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelIdentificadores.gridx = 0;
		gbc_panelIdentificadores.gridy = 4;
		
		this.getPanelDeInformacion().add(this.panelIdentificadores, gbc_panelIdentificadores);
	}

}